<?php

class Tools {
  /**
   * Random password generator
   *
   * @param integer $length Desired length (optional)
   * @return string Password
   */
  static public function passwdGen($length = 8) {
    $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    for ($i = 0, $passwd = ''; $i < $length; $i++)
      $passwd .= Tools::substr($str, mt_rand(0, Tools::strlen($str) - 1), 1);
    return $passwd;
  }

  /**
   * Get current url (only script name and query string)
   *
   * @return string Url
   */
  static public function getCurrentURL() {
    $sfu = $_SERVER['SCRIPT_NAME'];
    $break = Explode('/', $sfu);
    $sfu = $break[count($break) - 1];
    if($_SERVER['QUERY_STRING']>' ') {
      $sfu .=  '?'.$_SERVER['QUERY_STRING'];
    }
    return $sfu;
  }

  /**
   * Get full url
   *
   * @return string Full url
   */
  static public function getFullURL() {
    $sfu = 'http';
    if($_SERVER['HTTPS']=='on') {
      $sfu .=  's';
    }
    $sfu .=  '://';
    if($_SERVER['SERVER_PORT']!='80') $sfu .=  $_SERVER['HTTP_HOST'].':'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
    else
      $sfu .=  $_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
    if($_SERVER['QUERY_STRING']>' ') {
      $sfu .=  '?'.$_SERVER['QUERY_STRING'];
    }
    return $sfu;
  }

  /**
   * Busca el url de vuelta en el query string, si no hay usa como url
   * el parametro que se pasa $url
   *
   * @param string $url Url para usar si no hay back url
   * @param boolean $admin Poner a true si estas en paginas de administración de sistema
   * @return string Url de vuelta
   */
  static public function getBackUrl($url, $admin = false) {
    $back_url = Tools::getValue("back_url");
    if (strlen($back_url) > 0) {
      return base64_decode($back_url);
    }
    return ( $admin ? 'admin/' : '').$url;
  }

  /**
   * Redirect user to another page
   *
   * @param string $url Desired URL
   * @param string $baseUri Base URI (optional)
   */
  static public function redirect($url, $baseUri = BASE_URL) {
    if (isset($_SERVER['HTTP_REFERER']) AND ($url == $_SERVER['HTTP_REFERER']))
      header('Location: '.$_SERVER['HTTP_REFERER']);
    else
      header('Location: '.$baseUri.$url);
    exit;
  }

  /**
   * Actualizar pagina.
   */
  static public function refresh() {
    self::redirect(self::getCurrentURL());
  }

  /**
   * Redirect url wich allready PS_BASE_URI
   *
   * @param string $url Desired URL
   */
  static public function redirectLink($url) {
    header('Location: '.$url);
    exit;
  }

  /**
   * Redirect user to another admin page
   *
   * @param string $url Desired URL
   */
  static public function redirectAdmin($url) {
    header('Location: '.BASE_URL.'admin/'.$url);
    exit;
  }

  /**
   * Get a value from $_POST / $_GET
   * if unavailable, take a default value
   *
   * @param string $key Value key
   * @param mixed $defaultValue (optional)
   * @return mixed Value
   */
  static public function getValue($key, $defaultValue = false) {
    global $cookie;

    if (!isset($key) OR empty($key) OR !is_string($key))
      return false;
    $ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $defaultValue));

    if (is_string($ret) === true)
      $ret = urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret)));

    return is_array($ret) ? $ret : stripslashes($ret);
  }

  static public function getIsset($key) {
    if (!isset($key) OR empty($key) OR !is_string($key))
      return false;
    return isset($_POST[$key]) ? true : (isset($_GET[$key]) ? true : false);
  }

  /**
   * Display date regarding to language preferences
   *
   * @param array $params Date, format...
   * @param object $smarty Smarty object for language preferences
   * @return string Date
   */
  static public function dateFormat($params, &$smarty) {
    return Tools::displayDate($params['date'], $smarty->ps_language->id, $params['full']);
  }

  /**
   * Display date regarding to language preferences
   *
   * @param string $date Date to display format UNIX
   * @param integer $id_lang Language id
   * @param boolean $full With time or not (optional)
   * @return string Date
   */
  static public function displayDate($date, $id_lang, $full = false, $separator='-') {
    if (!$date OR !strtotime($date))
      return $date;
    if (!Validate::isDate($date) OR !Validate::isBool($full))
      die (Tools::displayError('Invalid date'));
    $tmpTab = explode($separator, substr($date, 0, 10));
    $hour = ' '.substr($date, -8);

    $language = DLanguage::getLanguage(intval($id_lang));
    if ($language AND strtolower($language['iso_code']) == 'fr')
      return ($tmpTab[2].'-'.$tmpTab[1].'-'.$tmpTab[0].($full ? $hour : ''));
    else
      return ($tmpTab[0].'-'.$tmpTab[1].'-'.$tmpTab[2].($full ? $hour : ''));
  }

  /**
   * Sanitize a string
   *
   * @param string $string String to sanitize
   * @param boolean $full String contains HTML or not (optional)
   * @return string Sanitized string
   */
  static public function safeOutput($string, $html = false) {
    if (!$html)
      $string = @htmlentities(strip_tags($string), ENT_QUOTES, 'utf-8');
    return $string;
  }

  static public function htmlentitiesUTF8($string) {
    if (is_array($string))
      return array_map(array('Tools', 'htmlentitiesUTF8'), $string);
    return htmlentities($string, ENT_QUOTES, 'utf-8');
  }

  static public function safePostVars() {
    $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST);
  }

  /**
   * Delete directory and subdirectories
   *
   * @param string $dirname Directory name
   */
  static public function deleteDirectory($dirname) {
    $files = scandir($dirname);
    foreach ($files as $file)
      if ($file != '.' AND $file != '..') {
        if (is_dir($file))
          self::deleteDirectory($file);
        elseif (file_exists($file))
          unlink($file);
        else
          echo 'Unable to delete '.$file;
      }
    rmdir($dirname);
  }

  /**
   * Display an error according to an error code
   *
   * @param integer $code Error code
   */
  static public function displayError($string = 'Hack attempt', $htmlentities = true) {
    global $_ERRORS;

    if (!is_array($_ERRORS))
      return str_replace('"', '&quot;', $string);
    $key = md5(str_replace('\'', '\\\'', $string));
    $str = (isset($_ERRORS) AND is_array($_ERRORS) AND key_exists($key, $_ERRORS)) ? ($htmlentities ? htmlentities($_ERRORS[$key], ENT_COMPAT, 'UTF-8') : $_ERRORS[$key]) : $string;
    return str_replace('"', '&quot;', stripslashes($str));
  }

  /**
   * Log a sql error, if any
   *
   * @param string $function The name of the function that gave error.
   * @return string $message Error message provider by mysql.
   * */
  static public function logMySqlError($function) {
    $error_msg = Db::getInstance()->getMsgError();
    if ($error_msg) {
      $last_query = Db::getInstance()->getLastQuery();
      Log::write("*** MySQL Error in $function: $error_msg ***");
      Log::write("*** Last MySQL query was: $last_query ***");
    }
  }

  /**
   * Display an error with detailed object
   *
   * @param object $object Object to display
   */
  static public function dieObject($object, $kill = true) {
    echo '<pre style="text-align: left;">';
    print_r($object);
    echo '</pre><br />';
    if ($kill)
      die('END');
  }

  /**
   * ALIAS OF dieObject() - Display an error with detailed object
   *
   * @param object $object Object to display
   */
  static public function d($object, $kill = true) {
    self::dieObject($object, $kill = true);
  }

  /**
   * ALIAS OF dieObject() - Display an error with detailed object but don't stop the execution
   *
   * @param object $object Object to display
   */
  static public function p($object) {
    self::dieObject($object, false);
  }

  /**
   * Check if submit has been posted
   *
   * @param string $submit submit name
   */
  static public function isSubmit($submit) {
    return (
            isset($_POST[$submit]) OR isset($_POST[$submit.'_x']) OR isset($_POST[$submit.'_y'])
                    OR isset($_GET[$submit]) OR isset($_GET[$submit.'_x']) OR isset($_GET[$submit.'_y'])
    );
  }

  /**
   * Encrypt password
   *
   * @param object $object Object to display
   */
  static public function encrypt($passwd) {
    return md5(pSQL(_COOKIE_KEY_.$passwd));
  }

  /**
   * Get token to prevent CSRF
   *
   * @param string $token token to encrypt
   */
  static public function getToken($page = true) {
    global $cookie;
    if ($page === true)
      return (Tools::encrypt($cookie->id_customer.$cookie->passwd.$_SERVER['SCRIPT_NAME']));
    else
      return (Tools::encrypt($cookie->id_customer.$cookie->passwd.$page));
  }

  /**
   * Encrypt password
   *
   * @param object $object Object to display
   */
  static public function getAdminToken($string) {
    return !empty($string) ? Tools::encrypt($string) : false;
  }

  static public function link_rewrite($str, $utf8_decode = false) {
    $purified = '';
    $length = Tools::strlen($str);
    if ($utf8_decode)
      $str = utf8_decode($str);
    for ($i = 0; $i < $length; $i++) {
      $char = Tools::substr($str, $i, 1);
      if (Tools::strlen(htmlentities($char)) > 1) {
        $entity = htmlentities($char, ENT_COMPAT, 'UTF-8');
        $purified .= $entity{1};
      }
      elseif (preg_match('|[[:alpha:]]{1}|u', $char))
        $purified .= $char;
      elseif (preg_match('<[[:digit:]]|-{1}>', $char))
        $purified .= $char;
      elseif ($char == ' ')
        $purified .= '-';
    }
    return $purified;
  }

  /**
   * Truncate strings
   *
   * @param string $str
   * @param integer $maxLen Max length
   * @param string $suffix Suffix optional
   * @return string $str truncated
   */
  /* CAUTION : Use it only on module hookEvents.
	** For other purposes use the smarty function instead */
  static public function truncate($str, $maxLen, $suffix = '...') {
    if (Tools::strlen($str) <= $maxLen)
      return $str;
    $str = utf8_decode($str);
    return (utf8_encode(substr($str, 0, $maxLen - Tools::strlen($suffix)).$suffix));
  }

  /**
   * Generate date form
   *
   * @param integer $year Year to select
   * @param integer $month Month to select
   * @param integer $day Day to select
   * @return array $tab html data with 3 cells :['days'], ['months'], ['years']
   *
   */
  static public function dateYears() {
    for ($i = date('Y') - 10; $i >= 1900; $i--)
      $tab[] = $i;
    return $tab;
  }

  static public function dateDays() {
    for ($i = 1; $i != 32; $i++)
      $tab[] = $i;
    return $tab;
  }

  static public function dateMonths() {
    for ($i = 1; $i != 13; $i++)
      $tab[$i] = date('F', mktime(0, 0, 0, $i, date('m'), date('Y')));
    return $tab;
  }
  
  static public function hourGenerate($hours, $minutes, $seconds) {
    return implode(':', array($hours, $minutes, $seconds));
  }

  static public function dateFrom($date) {
    $tab = explode(' ', $date);
    if (!isset($tab[1]))
      $date .= ' ' . Tools::hourGenerate(0, 0, 0);
    return $date;
  }

  static public function dateTo($date) {
    $tab = explode(' ', $date);
    if (!isset($tab[1]))
      $date .= ' ' . Tools::hourGenerate(23, 59, 59);
    return $date;
  }

  static public function getExactTime() {
    return time()+microtime();
  }

  static function strtolower($str) {
    if (function_exists('mb_strtolower'))
      return mb_strtolower($str, 'utf-8');
    return strtolower($str);
  }

  static function strlen($str) {
    if (function_exists('mb_strlen'))
      return mb_strlen($str, 'utf-8');
    return strlen($str);
  }

  static function strtoupper($str) {
    if (function_exists('mb_strtoupper'))
      return mb_strtoupper($str, 'utf-8');
    return strtoupper($str);
  }

  static function substr($str, $start, $length = false, $encoding = 'utf-8') {
    if (function_exists('mb_substr'))
      return mb_substr($str, $start, ($length === false ? Tools::strlen($str) : $length), $encoding);
    return substr($str, $start, $length);
  }

  static function ucfirst($str) {
    return self::strtoupper(Tools::substr($str, 0, 1)).Tools::substr($str, 1);
  }

  static public function iconv($from, $to, $string) {
    $converted = htmlentities($string, ENT_NOQUOTES, $from);
    $converted = html_entity_decode($converted, ENT_NOQUOTES, $to);
    return $converted;
  }

  static public function get_current_time() {
    return strftime("%Y-%m-%d %H:%M:%S", time());
  }

  static public function get_current_time_only() {
    return strftime("%H:%M:%S", time());
  }

  static public function parseDateAndTime($date, $display_time = false) {
    list($d, $t) = split(' ',$date);
    list($yr,$mon,$day) = split('-',$d);
    list($hr,$min,$sec) = split(':',$t);
    $format = 'd/m/Y';
    if ($display_time)
      $format = 'd/m/Y H:i';
    return date($format, mktime($hr,$min,$sec,$mon,$day,$yr));
  }

  static public function mysql2timestamp($date) {
    list($d, $t) = split(' ',$date);
    list($yr,$mon,$day) = split('-',$d);
    list($hr,$min,$sec) = split(':',$t);
    return mktime($hr,$min,$sec,$mon,$day,$yr);
  }

  static public function parseDate($date, $mode = '') {
    if (!$date) {
      return "";
    }
    switch ($mode) {
      case "short_year":
        list($yr,$mon,$day) = split('-',$date);
        $yr = substr($yr, 2, 4);
        return "$day/$mon/$yr";
        break;
      case "long_year":
        list($yr,$mon,$day) = split('-',$date);
        return "$day/$mon/$yr";
        break;
      case "short_year_to_db":
        list($day,$mon,$yr) = split('/',$date);
        $yr = "20".$yr;
        return "$yr-$mon-$day";
        break;
      case "long_year_to_db":
        list($day,$mon,$yr) = split('/',$date);
        return "$yr-$mon-$day";
        break;
      default:
        list($yr,$mon,$day) = split('-',$date);
        return "$day/$mon/$yr";
        break;
    }
  }

  static public function checkSQL($sql) {
    $sql = str_replace("'","''", $sql);
    return $sql;
  }

  static public function escapeJS($str) {
    $str = str_replace("'","\'", $str);
    return $str;
  }

  /* returns the current url without parameters you specify - $url = urlWithout("page,name,test"); */
  static public function urlWithout($elementsToRemove, $attatchLastAmp = true, $useGET = false) {

    $originalURL = "";
    $originalQueryString = "";
    $amp = "";
    $newQueryString = "";
    $q = "";
    $elementsToRemoveArray = array();
    $queryStringItems = array();
    $originalURL = $_SERVER['SCRIPT_NAME'];
    $originalQueryString = $_SERVER['QUERY_STRING'];
    if (strlen($originalQueryString) > 0 || $useGET) {
      if (strlen($elementsToRemove) > 0) {
        $elementsToRemoveArray = split(",", $elementsToRemove);
        if ($useGET) {
          $queryStringItems = $_GET;
          // Tools::print_pre($GLOBALS['_GET']);
          foreach ($queryStringItems as $key => $value) {
            if (!in_array($key, $elementsToRemoveArray)) {
              if (!is_array($value)) {
                $newQueryString = $newQueryString . $amp . $key.'='.$value;
                $amp = "&amp;";
              } else {
                foreach ($value as $val) {
                  $newQueryString = $newQueryString . $amp . $key.'[]='.$val;
                  $amp = "&amp;";
                }
              }
            }
          }
        } else {
          $queryStringItems = split("&", $originalQueryString);
          for ($q = 0; $q < sizeof($queryStringItems); $q++) {
            if (!in_array(Tools::getItemName($queryStringItems[$q]), $elementsToRemoveArray)) {
              $newQueryString = $newQueryString . $amp . $queryStringItems[$q];
              $amp = "&amp;";
            }
          }
        }
        if (strlen($newQueryString) > 0) {
          return $originalURL . "?" . $newQueryString . ($attatchLastAmp ? "&amp;" : '');
        } else {
          return $originalURL . "?";
        }
      } else {
        return $originalURL . "?" . $originalQueryString;
      }
    } else {
      return $originalURL . "?";
    }
  }

  /* needed by urlWithout function */
  static function getItemName($queryItem) {
    $getName = array();
    if (strlen($queryItem) > 0) {
      $getName = split("=", $queryItem);
      return $getName[0];
    } else {
      return "";
    }
  }

  // Print a variable or array inside a <pre> html tag or save the output of print_r into a variable
  static public function print_pre($variable, $return = false) {

    // Echo if return is false
    if (!$return) echo '<pre>';

    if ($return)
      return	print_r($variable, true); // Return contents to put in a variable
    else
      print_r($variable); // Echo contents

    // Echo if return is false
    if (!$return) echo '</pre>';
  }

  /**
   * Calculates the diference in days between two dates.
   *
   * @param string $start_date Start date (format yyyy-mm-dd)
   * @param string $end_date End date (format yyyy-mm-dd)
   * @param boolean $include_end_date Include end date in calculation (1 day is added)
   *
   * @return integer Number of days.
   * */
  static function daysBetweenDates($start_date, $end_date, $include_end_date = false) {

    // Timestamp for start date
    list($s_year, $s_month, $s_day) = explode("-", $start_date);
    $start_date_timestamp = mktime(0,0,0,$s_month,$s_day,$s_year);

    // Timestamp for end date
    list($e_year, $e_month, $e_day) = explode("-", $end_date);
    $end_date_timestamp = mktime(0,0,0,$e_month,$e_day,$e_year);

    // Diference between dates
    $diff = ($end_date_timestamp - $start_date_timestamp);
    $days = floor($diff/(60*60*24));

    if ($include_end_date)
      $days++;

    return $days;
  }

  function jEscape ($str) {
    if ($str) {
      return str_replace("'","\'",$str);
    }
    return '';
  }

  public function output_file($file, $name, $mime_type='') {
    /*
		 This function takes a path to a file to output ($file), 
		 the filename that the browser will see ($name) and 
		 the MIME type of the file ($mime_type, optional).
		 
		 If you want to do something on download abort/finish,
		 register_shutdown_function('function_name');
    */
    if(!is_readable($file)) die('File not found or inaccessible!');

    $size = filesize($file);
    $name = rawurldecode($name);

    /* Figure out the MIME type (if not specified) */
    $known_mime_types=array(
            "pdf" => "application/pdf",
            "txt" => "text/plain",
            "html" => "text/html",
            "htm" => "text/html",
            "exe" => "application/octet-stream",
            "zip" => "application/zip",
            "doc" => "application/msword",
            "xls" => "application/vnd.ms-excel",
            "ppt" => "application/vnd.ms-powerpoint",
            "gif" => "image/gif",
            "png" => "image/png",
            "jpeg"=> "image/jpg",
            "jpg" =>  "image/jpg",
            "php" => "text/plain"
    );

    if($mime_type=='') {
      $file_extension = strtolower(substr(strrchr($file,"."),1));
      if(array_key_exists($file_extension, $known_mime_types)) {
        $mime_type=$known_mime_types[$file_extension];
      } else {
        $mime_type="application/force-download";
      };
    };

    @ob_end_clean(); //turn off output buffering to decrease cpu usage

    // required for IE, otherwise Content-Disposition may be ignored
    if(ini_get('zlib.output_compression'))
      ini_set('zlib.output_compression', 'Off');

    header('Content-Type: ' . $mime_type);
    header('Content-Disposition: attachment; filename="'.$name.'"');
    header("Content-Transfer-Encoding: binary");
    header('Accept-Ranges: bytes');

    /* The three lines below basically make the
		    download non-cacheable */
    header("Cache-control: private");
    header('Pragma: private');
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

    // multipart-download and download resuming support
    if(isset($_SERVER['HTTP_RANGE'])) {
      list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
      list($range) = explode(",",$range,2);
      list($range, $range_end) = explode("-", $range);
      $range=intval($range);
      if(!$range_end) {
        $range_end=$size-1;
      } else {
        $range_end=intval($range_end);
      }

      $new_length = $range_end-$range+1;
      header("HTTP/1.1 206 Partial Content");
      header("Content-Length: $new_length");
      header("Content-Range: bytes $range-$range_end/$size");
    } else {
      $new_length=$size;
      header("Content-Length: ".$size);
    }

    /* output the file itself */
    $chunksize = 1*(1024*1024); //you may want to change this
    $bytes_send = 0;
    if ($file = fopen($file, 'r')) {
      if(isset($_SERVER['HTTP_RANGE']))
        fseek($file, $range);

      while(!feof($file) &&
              (!connection_aborted()) &&
              ($bytes_send<$new_length)
      ) {
        $buffer = fread($file, $chunksize);
        print($buffer); //echo($buffer); // is also possible
        flush();
        $bytes_send += strlen($buffer);
      }
      fclose($file);
    } else die('Error - can not open file.');

    die();
  }

  static public function cutString($str, $chars) {
    $chars = intval($chars);
    if ($chars > 0) {
      if (strlen($str) > $chars) {
        return substr($str, 0, $chars).'..';
      }
    }
    return $str;
  }

  static function returnJs($str) {
    return '<script type="text/javascript">'.$str.'</script>';
  }

  static public function setFlash($msg, $is_error = false) {
    if ($is_error) {
      $_SESSION['errors'] = $msg;
    } else {
      $_SESSION['confirms'] = $msg;
    }
  }

  static public function getFlash(&$array, $is_error = false) {
    if ($is_error) {
      if (isset($_SESSION['errors']) && strlen($_SESSION['errors'])>0) {
        $result = $_SESSION['errors'];
        unset($_SESSION['errors']);
        $array[] = $result;
      }
    }  else {
      if (isset($_SESSION['confirms']) && strlen($_SESSION['confirms'])>0) {
        $result = $_SESSION['confirms'];
        unset($_SESSION['confirms']);
        $array[] = $result;
      }
    }
  }

  static public function setNotice($msg) {
    $_SESSION['notice'] = $msg;
  }

  static public function getNotice(&$str, $remove = true) {
    if (isset($_SESSION['notice']) && strlen($_SESSION['notice'])>0) {
      $result = $_SESSION['notice'];
      if ($remove)
        unset($_SESSION['notice']);
      $str = $result;
    }
  }

  static public function file_extension($filename) {
    $path_info = pathinfo($filename);
    return $path_info['extension'];
  }

  static public function findexts($filename) {
    $filename = strtolower($filename) ;
    $exts = split("[/\\.]", $filename) ;
    $n = count($exts)-1;
    $exts = $exts[$n];
    return $exts;
  }
}

?>
